home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / libpq / fe-pqufs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  12.4 KB  |  594 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *      fe-pqufs.c
  4.  *
  5.  *   DESCRIPTION
  6.  *      Unix filesystem abstractions for large objects
  7.  *
  8.  *   SUPPORT ROUTINES
  9.  *
  10.  *   INTERFACE ROUTINES
  11.  *      p_open,p_read,p_write,p_close
  12.  *      p_creat, p_lseek, p_tell
  13.  *      p_stat
  14.  *      p_rename, p_mkdir, p_rmdir, p_unlink
  15.  *      p_opendir, p_readdir, p_rewinddir, p_closedir
  16.  *      p_chdir, p_getwd
  17.  *
  18.  *      For description, see below and unix man(2) pages.
  19.  *
  20.  *   NOTES
  21.  *      These routines are NOT compiled into the postgres backend,
  22.  *      rather they end up in libpq.a.
  23.  *
  24.  *   IDENTIFICATION
  25.  *      $Header: /private/postgres/src/lib/libpq/RCS/fe-pqufs.c,v 1.11 1992/06/15 08:24:49 dpassage Exp $
  26.  * ----------------------------------------------------------------
  27.  */
  28.  
  29. /*
  30.  * Unix abstractions for large objects.
  31.  *
  32.  * p_open, p_read, p_write, p_close
  33.  *
  34.  * p_creat, p_lseek, p_tell
  35.  * p_ftruncate *
  36.  *
  37.  * p_stat (certain fields in the stat structure, e.g device, are
  38.  *         meaningless.  Other fields, such as the times, are not valid yet.)
  39.  *
  40.  * p_rename, p_mkdir, p_rmdir, p_unlink
  41.  *
  42.  * p_opendir, p_readdir, p_rewinddir, p_closedir
  43.  *
  44.  *
  45.  * These p_* calls are translated to fastpath function calls in backend's 
  46.  * address space.  The large object file handles reside in, and the 
  47.  * operations occur in backend's address space.
  48.  *
  49.  * These two calls are local functions that do not call the fastpath.  Each 
  50.  * pathname in the p_* calls are translated to an absolute pathname using the
  51.  * current working directory, initially "/".
  52.  * p_chdir *
  53.  * p_getwd *
  54.  *
  55.  * The semantics of the p_* calls are, for the most part, the same as the 
  56.  * unix calls.
  57.  *
  58.  * Extent of the similarity with the Unix filesystem
  59.  * -------------------------------------------------
  60.  * There is no idea or support of a '.' or '..' file.  The functions opendir, 
  61.  * readdir, telldir, seekdir, rewinddir and closedir are instead implemented 
  62.  * as queries.
  63.  */
  64.  
  65. #include "tmp/simplelists.h"
  66. #include "tmp/libpq.h"
  67. #include "tmp/libpq-fe.h"
  68. #include "tmp/libpq-fs.h"
  69. #include "utils/fmgr.h"
  70. #include "tmp/postgres.h"
  71. #include "tmp/fastpath.h"
  72.  
  73. #ifndef MAXPATHLEN
  74. #define MAXPATHLEN 1024
  75. #endif
  76.  
  77. /* cwdir set from PFCWD environment variable, if available, else default */
  78. char cwdir[MAXPATHLEN] = "/";            /* current working directory */
  79.  
  80. /*
  81.  * Forward declarations for functions used later in this module
  82.  */
  83. static PDIR *new_PDIR ARGS((void ));
  84. static Direntry *new_Direntry ARGS((char *name , oid OIDf ));
  85. static char *resolve_path ARGS((char *path ));
  86. int p_errno = 0;            /* error code */
  87.  
  88. int p_open(fname,mode)
  89.      char *fname;
  90.      int mode;
  91. {
  92.     int fd;
  93.     PQArgBlock argv[2];
  94.     char *ret;
  95.  
  96.     argv[0].isint = 0;
  97.     argv[0].len = VAR_LENGTH_ARG;
  98.     argv[0].u.ptr = (int *)resolve_path(fname);
  99.  
  100.     argv[1].isint = 1;
  101.     argv[1].len = 4;
  102.     argv[1].u.integer = mode;
  103.     
  104.     ret = PQfn(F_LOOPEN,&fd,sizeof(int32),NULL,1,argv,2); 
  105.     if (ret == NULL)
  106.       return -1;
  107.     else if (*ret == 'V')
  108.       return -1;
  109.     else {
  110.     p_errno = fd>=0 ? 0 : -fd;
  111.  
  112.     /* have to do this to reset offset in shared fd cache */
  113.     /* but only if fd is valid */
  114.     if (fd >= 0 && p_lseek(fd, 0L, L_SET) < 0)
  115.         return -1;
  116.  
  117.     return fd;
  118.     }
  119. }
  120.  
  121. int p_close(fd)
  122.      int fd;
  123. {
  124.     PQArgBlock argv[1];
  125.     char *pqret;
  126.     int retval;
  127.  
  128.     argv[0].isint = 1;
  129.     argv[0].len = 4;
  130.     argv[0].u.integer = fd;
  131.     pqret = PQfn(F_LOCLOSE,&retval,sizeof(int32),NULL,1,argv,1);
  132.     if (pqret == NULL)
  133.       return -1;
  134.     else if (*pqret == 'V')
  135.       return -1;
  136.     else {
  137.     p_errno = retval>=0 ? 0 : -retval;
  138.     return retval;
  139.     }
  140. }
  141.  
  142. int p_read(fd, buf, len)
  143.      int fd;
  144.      char *buf;
  145.      int len;
  146. {
  147.     return (PQfsread(fd, buf, len));
  148. }
  149.  
  150. int p_write(fd, buf, len)
  151.      int fd;
  152.      char *buf;
  153.      int len;
  154. {
  155.     return (PQfswrite(fd, buf, len));
  156. }
  157.  
  158. int p_lseek(fd,offset,whence)
  159.      int fd, offset, whence;
  160. {
  161.     PQArgBlock argv[3];
  162.     char *pqret;
  163.     int retval;
  164.     
  165.     argv[0].isint = 1;
  166.     argv[0].len = 4;
  167.     argv[0].u.integer = fd;
  168.     
  169.     argv[1].isint = 1;
  170.     argv[1].len = 4;
  171.     argv[1].u.integer = offset;
  172.  
  173.     argv[2].isint = 1;
  174.     argv[2].len = 4;
  175.     argv[2].u.integer = whence;
  176.  
  177.     pqret = PQfn(F_LOLSEEK,&retval,sizeof(int32),NULL,1,argv,3);
  178.  
  179.     if (pqret == NULL)
  180.       return -1;
  181.     else if (*pqret == 'V')
  182.       return -1;
  183.     else {
  184.     p_errno = retval>=0 ? 0 : -retval;
  185.     return retval;
  186.     }
  187. }
  188.  
  189. int p_creat(path,mode,objtype)
  190.      char *path;
  191.      int mode;
  192.      int objtype;
  193. {
  194.     PQArgBlock argv[3];
  195.     char *pqret;
  196.     int retval;
  197.  
  198.     argv[0].isint = 0;
  199.     argv[0].len = VAR_LENGTH_ARG;
  200.     argv[0].u.ptr = (int *)resolve_path(path);
  201.  
  202.     argv[1].isint = 1;
  203.     argv[1].len = 4;
  204.     argv[1].u.integer = mode;
  205.  
  206.     argv[2].isint = 1;
  207.     argv[2].len = 4;
  208.     argv[2].u.integer = objtype;
  209.  
  210.     pqret = PQfn(F_LOCREAT,&retval,sizeof(int32),NULL,1,argv,3);
  211.  
  212.     if (pqret == NULL)
  213.       return -1;
  214.     else if (*pqret == 'V')
  215.       return -1;
  216.     else {
  217.     p_errno = retval>=0 ? 0 : -retval;
  218.     return retval;
  219.     }
  220. }
  221.  
  222. int p_tell(fd)
  223.      int fd;
  224. {
  225.     int retval;
  226.     PQArgBlock argv[1];
  227.     char *pqret;
  228.  
  229.     argv[0].isint = 1;
  230.     argv[0].len = 4;
  231.     argv[0].u.integer = fd;
  232.  
  233.     pqret = PQfn(F_LOTELL,&retval,sizeof(int32),NULL,1,argv,1);
  234.  
  235.     if (pqret == NULL)
  236.       return -1;
  237.     else if (*pqret == 'V')
  238.       return -1;
  239.     else {
  240.     p_errno = retval>=0 ? 0 : -retval;
  241.     return retval;
  242.     }
  243. }
  244.  
  245. int p_mkdir(path,mode)
  246.      char *path;
  247.      int mode;
  248. {
  249.     PQArgBlock argv[2];
  250.     char *pqret;
  251.     int retval;
  252.  
  253.     argv[0].isint = 0;
  254.     argv[0].len = VAR_LENGTH_ARG;
  255.     argv[0].u.ptr = (int *)resolve_path(path);
  256.  
  257.     argv[1].isint = 1;
  258.     argv[1].len = 4;
  259.     argv[1].u.integer = mode;
  260.  
  261.     pqret = PQfn(F_LOMKDIR,&retval,sizeof(int32),NULL,1,argv,2);
  262.  
  263.     if (pqret == NULL)
  264.       return -1;
  265.     else if (*pqret == 'V')
  266.       return -1;
  267.     else {
  268.     p_errno = retval>=0 ? 0 : -retval;
  269.     return retval;
  270.     }
  271. }
  272.  
  273. int p_unlink(path)
  274.      char *path;
  275. {
  276.     PQArgBlock argv[1];
  277.     char *pqret;
  278.     int retval;
  279.  
  280.     argv[0].isint = 0;
  281.     argv[0].len = VAR_LENGTH_ARG;
  282.     argv[0].u.ptr = (int *)resolve_path(path);
  283.  
  284.     pqret = PQfn(F_LOUNLINK,&retval,sizeof(int32),NULL,1,argv,1);
  285.  
  286.     if (pqret == NULL)
  287.       return -1;
  288.     else if (*pqret == 'V')
  289.       return -1;
  290.     else {
  291.     p_errno = retval>=0 ? 0 : -retval;
  292.     return retval;
  293.     }
  294. }
  295.  
  296. int p_rmdir(path)
  297.      char *path;
  298. {
  299.     PQArgBlock argv[1];
  300.     char *pqret;
  301.     int retval;
  302.  
  303.     argv[0].isint = 0;
  304.     argv[0].len = VAR_LENGTH_ARG;
  305.     argv[0].u.ptr = (int *)resolve_path(path);
  306.  
  307.     pqret = PQfn(F_LORMDIR,&retval,sizeof(int32),NULL,1,argv,1);
  308.  
  309.     if (pqret == NULL)
  310.       return -1;
  311.     else if (*pqret == 'V')
  312.       return -1;
  313.     else {
  314.     p_errno = retval>=0 ? 0 : -retval;
  315.     return retval;
  316.     }
  317. }
  318.  
  319. int p_ferror(fd)
  320.      int fd;
  321. {
  322.     return 0; /* no errors reported yet... */
  323. }
  324.  
  325. int p_rename(path,pathnew)
  326.      char *path, *pathnew;
  327. {
  328.     PQArgBlock argv[2];
  329.     char *pqret;
  330.     int retval;
  331.     static char tmpdir[MAXPATHLEN];
  332.     strcpy(tmpdir,resolve_path(path));
  333.     argv[0].isint = 0;
  334.     argv[0].len = VAR_LENGTH_ARG;
  335.     argv[0].u.ptr = (int *)tmpdir;
  336.  
  337.     argv[1].isint = 0;
  338.     argv[1].len = VAR_LENGTH_ARG;
  339.     argv[1].u.ptr = (int *)resolve_path(pathnew);
  340.  
  341.     pqret = PQfn(F_LORENAME,&retval,sizeof(int32),NULL,1,argv,2);
  342.  
  343.     if (pqret == NULL)
  344.       return -1;
  345.     else if (*pqret == 'V')
  346.       return -1;
  347.     else {
  348.     p_errno = retval>=0 ? 0 : -retval;
  349.     return retval;
  350.     }
  351. }
  352.  
  353. int p_stat(path,statbuf)
  354.      char *path;
  355.      struct pgstat *statbuf;
  356. {
  357.     int stlen;
  358.     PQArgBlock argv[2];
  359.     struct varlena *statres;
  360.     int vstatlen;
  361.     char *pqret;
  362.  
  363.     argv[0].isint = 0;
  364.     argv[0].len = VAR_LENGTH_ARG;
  365.     argv[0].u.ptr = (int *)resolve_path(path);
  366.  
  367. /* PQfn deals with >4byte return values fine. */
  368. /*    vstatlen = sizeof(struct pgstat) + sizeof(int);
  369.     statres = (struct varlena *) palloc(vstatlen); */
  370.     pqret = PQfn(F_LOSTAT,(int *)statbuf,sizeof(struct pgstat),&stlen,2,argv,1);
  371. /*    bcopy((char *) VARDATA(statres), (char *) statbuf, sizeof(struct pgstat));
  372.     pfree(statres); */
  373.  
  374.     if (stlen == 5) {
  375.     p_errno = PENOENT;
  376.         return -1;
  377.     }
  378.  
  379.     if (pqret == NULL)
  380.       return -1;
  381.     else if (*pqret == 'V')
  382.       return -1;
  383.     else {
  384.     return 0;
  385.     }
  386. }
  387.  
  388.  
  389. /*
  390.  * open a portal to the query 
  391.  * 'retrieve portal dir (pg_naming.filename) where pg_naming.parentid =
  392.  * id-of-directory'
  393.  */
  394. PDIR *p_opendir(path)
  395.      char *path;
  396. {
  397.     /* Get OID of directory (path) */
  398.     int stlen;
  399.     PQArgBlock argv[2];
  400.     char *pqret;
  401.     oid pathOID;
  402.  
  403.     argv[0].isint = 0;
  404.     argv[0].len = VAR_LENGTH_ARG;
  405.     argv[0].u.ptr = (int *)resolve_path(path);
  406.  
  407.     pqret = PQfn(F_FILETOOID,(int *)&pathOID,sizeof(int32),NULL,1,argv,1);
  408.     if (pqret == NULL)
  409.       return NULL;
  410.     else if (*pqret == 'V')
  411.       return NULL;
  412.     else {
  413.     PDIR *pdir = new_PDIR();
  414.     char query[512];
  415.     char *res;
  416.  
  417. #if 0
  418.     if ((res == NULL) || (*res != 'C')) { /* CBEGIN */
  419.         return NULL;
  420.     }
  421. #endif
  422.     sprintf(query,"retrieve (pg_naming.filename,pg_naming.ourid) where pg_naming.parentid = \"%d\"::oid",pathOID);
  423.     res = PQexec(query);
  424.     if ((res != NULL) && (*res == 'P')) /* CRETRIEVE */
  425.     {
  426.         PortalBuffer *p;
  427.         int k,g,t;
  428.         p = PQparray(++res);
  429.         g = PQngroups(p);
  430.         t = 0;
  431.         for (k=0;k<g;k++) {
  432.         int m,n,i;
  433.         n = PQntuplesGroup(p,k);
  434.         m = PQnfieldsGroup(p,k);
  435.         for (i =0;i<n;i++) {
  436.             char *name = PQgetvalue(p,t+i,0);
  437.             oid OIDf = atoi(PQgetvalue(p,t+i,1));
  438.             Direntry *d = new_Direntry(name,OIDf);
  439.             SLAddTail(&pdir->dirlist,&d->Node);
  440.         }
  441.         t += n;
  442.         }
  443.     }
  444.     pdir->current_entry = (Direntry *)SLGetHead(&pdir->dirlist);
  445.     return pdir;
  446.     }
  447. }
  448.  
  449. struct pgdirent *p_readdir(dirp)
  450.      PDIR *dirp;
  451. {
  452.     struct pgdirent *d = NULL;
  453.     if (dirp->current_entry != NULL) {
  454.     d = &dirp->current_entry->d;
  455.     dirp->current_entry = (Direntry *)SLGetSucc(&dirp->current_entry->Node);
  456.     }
  457.     return d;
  458. }
  459.  
  460. void p_rewinddir(dirp)
  461.      PDIR *dirp;
  462. {
  463.     dirp->current_entry = (Direntry *)SLGetHead(&dirp->dirlist);
  464. }
  465.  
  466. int p_closedir(dirp)
  467.      PDIR *dirp;
  468. {
  469.     /* well, how does one garbage collect these things? */
  470. }
  471.  
  472. int p_chdir(path)
  473.      char *path;
  474. {
  475.     struct pgstat st;
  476.  
  477.     if (p_stat(path,&st) < 0) {
  478.     return -1;
  479.     }
  480.     if (!S_ISDIR(st.st_mode)) {
  481.     p_errno = PENOTDIR;
  482.     return -1;
  483.     }
  484.     
  485.     if (*path == '/') {
  486.     strcpy(cwdir,path);
  487.     } else {
  488.     strcpy(cwdir,resolve_path(path));
  489.     }
  490.     setenv("PFCWD",cwdir,1);
  491.     return 0;
  492. }
  493.  
  494. char *p_getwd(path)
  495.      char *path;
  496. {
  497.     char *foo;
  498.     foo = resolve_path("/");     /* initialize cwdir, if necessary */
  499.     strcpy(path,cwdir);
  500.     return path;
  501. }
  502.  
  503. /*
  504.  * ------------------------------------------------
  505.  * Support routines for DIR operations
  506.  * ------------------------------------------------
  507.  */
  508. static PDIR *new_PDIR()
  509. {
  510.     PDIR *p;
  511.     p = (PDIR *)palloc(sizeof(PDIR));
  512.     SLNewList(&p->dirlist,offsetof(Direntry,Node));
  513.     p->current_entry = NULL;
  514.     return p;
  515. }
  516.  
  517. static Direntry *new_Direntry(name,OIDf)
  518.      char *name;
  519.      oid OIDf;
  520. {
  521.     Direntry *d;
  522.     d = (Direntry *)palloc(sizeof(Direntry));
  523.     SLNewNode(&d->Node);
  524.     d->d.d_ino = OIDf;
  525.     strcpy(d->d.d_name,name);
  526.     return d;
  527. }
  528. /* use by all the p_* routines to map relative to absolute path */
  529. #define EOP(x) ((x)=='/' ||(x) =='\0')
  530. #define DOT(x) ((x) =='.')
  531.  
  532. static int cwdinit = 0;
  533.  
  534. /* Be careful, the result returned is statically allocated*/
  535. static char *resolve_path(gpath)
  536.      char *gpath;
  537. {
  538.     char *cp;
  539.     static char thenewdir[MAXPATHLEN];
  540.     char tpath[MAXPATHLEN];
  541.     char *path = tpath;
  542.     strcpy(path,gpath);
  543.  
  544.     if (!cwdinit) {
  545.     if ((cp = (char *)getenv("PFCWD")) != NULL)
  546.         strcpy(cwdir,cp);
  547.     cwdinit = 1;
  548.     }
  549.     if (*path == '/') {
  550.     strcpy(thenewdir,path);
  551.     return thenewdir;
  552.     }
  553.     strcpy(thenewdir,cwdir);
  554.     while (path && *path) {
  555.     if (DOT(path[0]) && DOT(path[1]) && EOP(path[2])) {
  556.         char *sep = (char *)rindex(thenewdir,'/');
  557.         if (path[2] == '/')
  558.           path += 3;
  559.         else
  560.           path += 2;
  561.         if (sep != NULL && sep != thenewdir) {
  562.         *sep = '\0';
  563.         } else {
  564.         thenewdir[0] = '/'; thenewdir[1] = '\0';
  565.         }
  566.         continue;
  567.     }
  568.     if (DOT(path[0]) && EOP(path[1])) {
  569.         if (path[1] == '/')
  570.           path += 2;
  571.         else
  572.           path += 1;
  573.         continue;
  574.     }
  575.     if (path[0]) {
  576.         char *comp = (char *)index(path,'/');
  577.         if (comp != NULL) {
  578.         *comp='\0';
  579.         if (thenewdir[1]) /* not simply "/" */
  580.           strcat(thenewdir,"/");
  581.         strcat(thenewdir,path);
  582.         path = comp+1;
  583.         } else {
  584.         if (thenewdir[1]) /* not simply "/" */
  585.           strcat(thenewdir,"/");
  586.         strcat(thenewdir,path);
  587.         path = NULL; /* end of all the components */
  588.         }
  589.         continue;
  590.     }
  591.     }
  592.     return thenewdir;
  593. }
  594.